/**
 ****************************************
 * @file lcd_drv.h
 * @author: AnRui
 * @version 0.1
 * @date  : 2025-05-29
 * @copyright Copyright (c) 2025
 * @desc:LCD屏幕的驱动程序
 *      为什么要选用exmc来驱动led？
 *          EXMC 允许将 LCD 控制器的寄存器和显存映射到 MCU 的地址空间中，CPU 可像访问内存一样直接读写 LCD，无需额外的驱动层，降低软件复杂度
 *      ID的获取流程: 1.发送命令 2.接受数据(无效的) 3.接受数据(00) 4.接收数据高8位 5.接收数据低8位
 *      注意:
 *          发送命令时 只有低8位有效
 * ***************************************
 */

#ifndef __LCD_DRV_H__
#define __LCD_DRV_H__
#include "gd32f30x.h"
#include <stdio.h>

 /************************LCD CONFIG*******************************/
#define LCD_PIXEL_WIDTH      320        // 横向像素点个数
#define LCD_PIXEL_HEIGHT     480        // 纵向像素点个数
#define LCD_ID         		   0x9488     // LCD设备ID
#define LCD_READ_ID_CMD      0xD3       // 读取ID的命令
#define LCD_X_CMD            0x2A       // LCD 设置X坐标命令
#define LCD_Y_CMD            0x2B       // LCD 设置Y坐标命令
#define LCD_WG_CMD           0x2C       // LCD_WG_CMD写数据命令

 /************************HONG COMMAND*******************************/
#define LcdSendCmd(cmdVal) 		(*(volatile uint16_t *)0x64000000) = cmdVal      // 发送命令 :向该地址写数据 
#define LcdSendData(dataVal) 	(*(volatile uint16_t *)0x64000002) = dataVal     // 发送数据
#define LcdGetData() 			    (*(volatile uint16_t *)0x64000002)               // 读取数据

// 背光开关
#define LCD_BACKLIGHT_ON() 		gpio_bit_set(GPIOA, GPIO_PIN_1)
#define LCD_BACKLIGHT_OFF()  	gpio_bit_reset(GPIOA, GPIO_PIN_1)

 /************************COLOR VALUE*******************************/
#define WHITE                 0xFFFF //白色
#define BLACK                 0x0000 //黑色
#define BLUE                  0x001F //蓝色
#define BRED                  0xF81F //红色
#define GRED                  0xFFE0 //红色
#define GBLUE                 0x07FF //蓝色
#define RED                   0xF800 //红色
#define MAGENTA               0xF81F //品红
#define GREEN                 0x07E0 //绿色
#define CYAN                  0x7FFF //青色
#define YELLOW                0xFFE0 //黄色
#define BROWN                 0xBC40 //棕色
#define BRRED                 0xFC07 //棕红色
#define GRAY                  0x8430 //灰色
 /************************FONT*******************************/
typedef enum {
	ASCII_FONT_SIZE_12 = 12,
	ASCII_FONT_SIZE_16 = 16,
	ASCII_FONT_SIZE_24 = 24,
	CHINESE_FONT_SIZE_16 = 16,
	CHINESE_FONT_SIZE_24 = 24,
}FontSizeEnum;

typedef struct {
	FontSizeEnum fontSize;
	uint16_t bgColor;
	uint16_t fontColor;
} FontInfoStruct;

/************************EXTERN FUNCTION*******************************/

/**
 * @desc  : LCD驱动初始化
 * @date  : 2025-06-03
 * @author: AnRui
 * @note  :
 */
void LcdDrvInit(void);

/**
 * @desc  : 在LCD指定区域填充纯色
 * @date  : 2025-06-03
 * @author: AnRui
 * @param : sx, sy - 矩形区域左上角坐标
 * @param : ex, ey - 矩形区域右下角坐标
 * @param : color  - 填充颜色（16位RGB565格式）
 * @note  :
 *   1. 坐标范围需在LCD有效区域内
 *   2. 颜色格式为RGB565: R[15:11], G[10:5], B[4:0]
 *   3. 填充过程中会锁定显示窗口，直到填充完成
 */
void LcdFillPureColor(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color);



/**
 * @desc  : 在LCD屏幕上指定区域填充多色彩数据
 * @date  : 2025-06-03
 * @author: AnRui
 * @param : sx - 起始点X坐标（左上角）
 * @param : sy - 起始点Y坐标（左上角）
 * @param : ex - 结束点X坐标（右下角）
 * @param : ey - 结束点Y坐标（右下角）
 * @param : color - 指向颜色数据数组的指针，需确保数组大小不小于填充区域总像素数
 * @note  :
 *        1. 坐标必须满足 sx ≤ ex 且 sy ≤ ey，否则函数将直接返回
 *        2. 函数假设color数组长度足够，调用者需自行保证数据有效性
 *        3. 填充方向为从左到右、从上到下的扫描线顺序
 *        4. 色彩格式取决于LCD控制器配置，通常为RGB565格式
 */
void LcdFillMultiColor(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t* color);



/**
 * @desc  : lcd 使用dma的发生发送数据
 * @date  : 2025-06-16
 * @author: AnRui
 * @param : sx - {参数说明}:
 * @param : sy - {参数说明}:
 * @param : ex - {参数说明}:
 * @param : ey - {参数说明}:
 * @note  : 具体的发送代码 由lvgl控制  这里只是做发送数据之前的配置
 */
void LcdFillMultiColorByDma(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey);

/**
 * @desc  : 在LCD屏幕上指定位置绘制单个像素点
 * @date  : 2025-06-03
 * @author: AnRui
 * @param : xPos - 像素点的X坐标
 * @param : yPos - 像素点的Y坐标
 * @param : color - 像素点的颜色值（通常为RGB565格式）
 * @note  : 左上角的坐标与左下角的坐标一致  右边也一样
 */
void LcdDrawPoint(uint16_t xPos, uint16_t yPos, uint16_t color);

/**
 * @desc  : 清屏
 * @date  : 2025-06-03
 * @author: AnRui
 * @param : color - {参数说明}:
 * @note  : 使用一个颜色填充整个屏幕
 */
void LcdClear(uint16_t color);

/**
 * @desc  : 在LCD上显示ACSII字符
 * @date  : 2025-06-04
 * @author: AnRui
 * @param : xPos - {参数说明}: 起始点X坐标（左上角）
 * @param : yPos - {参数说明}: 起始点Y坐标（左上角）
 * @param : FontInfoStruct - {参数说明}: 字体信息结构体 包含字体背景色 字体颜色 字体大小
 * @note  : 如果字体的大小不是8的倍数 会自动补0 在发送的时候要注意去调
 *					尽量保证函数不超过4个参数
 */
void LcdShowAscii(uint16_t xPos, uint16_t yPos, char font, FontInfoStruct* fontInfo);



/**
 * @desc  : 在LCD上显示ASCII字符串
 * @date  : 2025-06-04
 * @author: AnRui
 * @param : xPos - {参数说明}:
 * @param : yPos - {参数说明}:
 * @param : string - {参数说明}:
 * @param : fontInfo - {参数说明}:
 * @note  :
 */
void LcdShowAsciiString(uint16_t xPos, uint16_t yPos, char* string, FontInfoStruct* fontInfo);


/**
 * @desc  : 在LCD屏幕上显示中文字符
 * @date  : 2025-06-04
 * @author: AnRui
 * @param : xPos - {参数说明}: 字符显示区域左上角的X坐标
 * @param : yPos - {参数说明}: 字符显示区域左上角的Y坐标
 * @param : fontArr - {参数说明}: 指向中文字符点阵数据的指针
 * @param : fontInfo - {参数说明}: 指向字体信息结构体的指针，包含字体大小、颜色等信息
 * @note  :
 */
void LcdShowChinese(uint16_t xPos, uint16_t yPos, uint8_t* fontArr, FontInfoStruct* fontInfo);
#endif
